﻿using Microsoft.Extensions.DependencyInjection;
using Modules.CheckIn;
using Modules.Payroll;
using Modules.Reports;
using Modules.System.Settings.Entitys;
using Modules.System.Settings;
using PmSoft;
using PmSoft.ApplicationContext;
using Microsoft.Extensions.Logging;
using Modules.Project;
using Modules.Corp;
using Modules.Project.Entitys;
using PmSoft.Entity;
using PmSoft.Events;
using Modules.Project.EventArgs;

namespace Modules.System.EarlyWarning;

/// <summary>
/// 预警记录表服务
/// </summary>
[UseDI(ServiceLifetime.Scoped)]
public class SysEarlyWarningService
{
    private readonly SysEarlyWarningRepository sysEarlyWarningRepository;
    private readonly WagePayrollService wagePayrollService;
    private readonly CheckinWorkHoursService checkinWorkHoursService;
    private readonly ReportProjectMonthService reportProjectMonthService;
    private readonly ProjectService projectService;
    private readonly IApplicationContext applicationContext;
    private readonly ILogger logger;
    private readonly ProjectLockLogService projectLockLogService;
    private readonly SettingManager<CheckinWageStatusSettings> settingManager;
    private readonly CheckinWageStatusSettings settings;
    private readonly IEventBus eventBus;
    private readonly CorpService corpService;
    private readonly ProjectCorpService projectCorpService;

    public SysEarlyWarningService(SysEarlyWarningRepository sysEarlyWarningRepository,
                                  WagePayrollService wagePayrollService,
                                  CheckinWorkHoursService checkinWorkHoursService,
                                  ReportProjectMonthService reportProjectMonthService,
                                  IApplicationContext applicationContext,
                                  ILogger<SysEarlyWarningService> logger,
                                  ProjectLockLogService projectLockLogService,
                                  SettingManager<CheckinWageStatusSettings> settingManager,
                                  ProjectService projectService,
                                  CorpService corpService,
                                  ProjectCorpService projectCorpService,
                                    IEventBus eventBus)
    {
        this.sysEarlyWarningRepository = sysEarlyWarningRepository;
        this.wagePayrollService = wagePayrollService;
        this.checkinWorkHoursService = checkinWorkHoursService;
        this.reportProjectMonthService = reportProjectMonthService;
        this.applicationContext = applicationContext;
        this.logger = logger;
        this.projectLockLogService = projectLockLogService;
        this.settingManager = settingManager;
        this.settings = settingManager.Get();
        this.projectService = projectService;
        this.corpService = corpService;
        this.projectCorpService = projectCorpService;
        this.eventBus = eventBus;
    }

    /// <summary>
    /// 预警记录表表单详情
    /// </summary>
    /// <param name="id">主键</param>
    /// <returns></returns>
    public SysEarlyWarning? Get(int id)
    {
        return sysEarlyWarningRepository.Get(id);
    }

    /// <summary>
    /// 批量删除，根据id
    /// </summary>
    /// <param name="ids">id的集合</param>
    public void Deleted(IEnumerable<int> ids)
    {
        foreach (int id in ids)
        {
            Delete(id);
        }
    }

    /// <summary>
    /// 单个删除
    /// </summary>
    /// <param name="id">主键</param>
    public void Delete(int id)
    {
        sysEarlyWarningRepository.DeleteByEntityId(id);
    }

    /// <summary>
    /// 创建预警记录表
    /// </summary>
    /// <param name="entity">实体对象</param>
    public void Create(SysEarlyWarning entity)
    {
        sysEarlyWarningRepository.Insert(entity);
    }

    /// <summary>
    /// 编辑预警记录表
    /// </summary>
    /// <param name="entity">实体对象</param>
    public void Update(SysEarlyWarning entity)
    {
        sysEarlyWarningRepository.Update(entity);
    }

    /// <summary>
    /// 预警记录表分页列表
    /// </summary>
    /// <param name="query">查询参数</param>
    /// <param name="pageIndex">当前页码</param>
    /// <param name="pageSize">每页显示条数</param>
    /// <returns></returns>
    public IPagedList<SysEarlyWarning> GetSysEarlyWarnings(SysEarlyWarningQuery query, int pageIndex, int pageSize)
    {
        return sysEarlyWarningRepository.GetSysEarlyWarnings(query, pageIndex, pageSize);
    }

    /// <summary>
    /// 创建预警记录表
    /// </summary>
    /// <param name="month"></param>
    /// <param name="needLock">是否需要锁定</param>
    public void CreateSysEarlyWarning(int month, bool needLock)
    {
        //未落实代发的项目月报表
        IEnumerable<ReportProjectMonth> reportProjectMonths = reportProjectMonthService.GetReportProjectsMonthsInWageStatus(month, new 落实状态[] { 落实状态.半落实, 落实状态.未落实, 落实状态.无需核实 });
        //IEnumerable<CheckinWorkHours> checkinWorkHours = checkinWorkHoursService.GetCheckinWorkHoursByProjectIdsAndMonth(reportProjectMonths.Select(a => a.ProjectId), month.ToString("yyyyMM"));
        //IEnumerable<WagePayroll> wagePayrolls = wagePayrollService.GetWagePayrollsByProjectIdsAndMonth(reportProjectMonths.Select(a => a.ProjectId), month.ToString("yyyyMM"));
        IEnumerable<ProjectInfo> projectInfos = projectService.GetProjects(reportProjectMonths.Select(a => a.ProjectId));


        foreach (var report in reportProjectMonths)
        {
            ProjectInfo? project = projectInfos.FirstOrDefault(a => a.ProjectId == report.ProjectId);
            if (project == null)
            {
                logger.LogError($"项目Id {report.ProjectId} 在项目表中没找到");
                continue;
            }
 
            CorpInfo? corpInfo = corpService.GetCorpInfo(project.LumpContractorCorpId);
            if (corpInfo == null)
            {
                logger.LogError($"项目{report.ProjectName}({project.PrjNum}) 总承包单位不存在，不能推送到一体化平台");
                continue;
            }
            #region 判断代发状态

            //代发状态： 1.实际考勤人数/实际发放人数 满足百分比显示对应的状态 
            int actualAttendance = 0;
            if (report.ActualAttendance > 0 && report.NumberProxyRecipients > 0)
            {
                actualAttendance = report.NumberProxyRecipients / report.ActualAttendance;
            }
            CheckinWageStatusSettings checkinSettings = settings;
            if (actualAttendance == checkinSettings.NotImplementedValue)
            {
                report.WageStatus = 落实状态.未落实;
            }
            else if (actualAttendance > checkinSettings.NotImplementedValue && actualAttendance <= checkinSettings.SemiImplementationValue)
            {
                report.WageStatus = 落实状态.半落实;
            }
            else if (actualAttendance > checkinSettings.SemiImplementationValue && actualAttendance <= checkinSettings.ImplementedValue)
            {
                report.WageStatus = 落实状态.已落实;
            }


            #endregion 判断代发状态
            try
            {
                applicationContext.Transaction.Begin();
                ProjectLockLog? projectLockLog = null;
                if (report.WageStatus == 落实状态.未落实 || report.WageStatus == 落实状态.半落实)
                {
                    report.WageStatus = 落实状态.半落实;
                    SysEarlyWarning sysEarlyWarning = new()
                    {
                        Code = DateTime.Now.ToString("yyyyMMddHHmmssfff"),
                        Tenant = 预警租户.Project,
                        ObjectId = report.ProjectId.ToString(),
                        WarningType = 预警类型.工资代发状态,
                        Remark = $"项目[{report.ProjectName}({project.PrjNum})]在{month}无代发记录",
                        CreateTime = DateTime.Now
                    };
                    Create(sysEarlyWarning);
                    if (needLock)
                    {
                        projectLockLog = new()
                        {
                            Code = DateTime.Now.ToString("yyyyMMddHHmmssfff"),
                            ProjectId = report.ProjectId,
                            LockPrjStatus = projectService.GetProjectInfo(report.ProjectId)?.PrjStatus,
                            HasLocked = true,
                            LockTime = DateTime.Now,
                            LockMonth = report.Month,
                            LockReason = sysEarlyWarning.Remark,
                            HasPush = false,
                            CreateTime = DateTime.Now
                        };
                        projectLockLogService.Create(projectLockLog);

                    }
                }
                //创建或更新项目月报表
                reportProjectMonthService.CreateOrUpdate(report);
                applicationContext.Transaction.Complete();
                //推送到一体化平台
                if (projectLockLog != null)
                    eventBus.PublishTo(this, new ProjectLockEventArgs(projectLockLog.Code, corpInfo.Code, project.Name));
            }
            catch (Exception ex)
            {
                logger.LogError("预警记录处理失败:" + ex.Message);
                applicationContext.Transaction.Abort();
            }
        }
    }
}